﻿using System;
using UnityEngine;

// 零碎扩展
public static class MathEx
{
    public static readonly float Pi = Mathf.PI;
    public static readonly float HalfPi = Pi / 2;
    public static readonly float Pi2 = Pi * 2;

    public static readonly float Left = Pi;
    public static readonly float Right = 0;
    public static readonly float Up = HalfPi;
    public static readonly float Down = HalfPi + Pi;

    public static readonly float Rad2Deg = 180 / Pi;
    public static readonly float Deg2Rad = Pi / 180;

    // 向量所指方向对应的欧拉角(0-2pi)
    public static float Arc(float dx, float dy)
    {
        return MathEx.Atan(dy, dx);
    }

    public static float Dir(float dx, float dy)
    {
        return Arc(dx, dy) * 180 / Pi;
    }

    // 截断到给定范围
    public static float Clamp(this float v, float min, float max)
    {
        if (v < min)
            return min;
        else if (v > max)
            return max;
        else
            return v;
    }

    // 计算转向，从当前朝向转向目标方向，并限制最大转动角度
    public static float CalcDir4Turn2(float nowDir, float turn2Dir, float maxAbs)
    {
        return CalcArc4Turn2(nowDir.Dir2Arc(), turn2Dir.Dir2Arc(), maxAbs.Dir2Arc()).Arc2Dir();
    }

    // 计算转向，从当前朝向转向目标方向，并限制最大转动角度
    public static float CalcArc4Turn2(float nowArc, float turn2Arc, float maxAbs)
    {
        var tv = (turn2Arc - nowArc).RangeInPi();
        if (Abs(maxAbs) < Abs(tv))
            return tv > 0 ? maxAbs : -maxAbs;
        else
            return tv;
    }

    // 将指定角度规范到 [-180, 180)
    public static float RangeIn180(this float dir)
    {
        var d = dir;
        while (d >= 180)
            d -= 360;

        while (d < -180)
            d += 360;

        return d;
    }

    // 将指定角度规范到 [0, 2 * Pi)
    public static float RangeInPi2(this float arc)
    {
        var d = arc;
        while (d < 0)
            d += Pi2;

        while (d >= Pi2)
            d -= Pi2;

        return d;
    }

    // 将指定角度规范到 [-Pi, Pi)
    public static float RangeInPi(this float arc)
    {
        var d = arc;
        while (d >= Pi)
            d -= Pi2;

        while (d < -Pi)
            d += Pi2;

        return d;
    }

    // 取绝对值
    public static float Abs(this float v)
    {
        return v >= 0 ? v : -v;
    }

    // 计算三角函数

    public static float Cos(float arc)
    {
        return Mathf.Cos(arc);
    }

    public static float Sin(float arc)
    {
        return Mathf.Sin(arc);
    }

    public static float Tan(float arc)
    {
        return Tan(arc);
    }

    public static float Atan(float y, float x)
    {
        return Mathf.Atan2(y, x);
    }

    public static float Sqrt(float v)
    {
        return Mathf.Sqrt(v);
    }

    public static float Max(float a, float b)
    {
        return a >= b ? a : b;
    }

    public static float Min(float a, float b)
    {
        return a <= b ? a : b;
    }

    public static float Arc2Dir(this float arc)
    {
        return arc * 180 / Pi;
    }

    public static float Dir2Arc(this float dir)
    {
        return dir * Pi / 180;
    }
}